package top.riske.gen3d.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.riske.gen3d.mapper.Hunyuan3DFileMapper;
import top.riske.gen3d.mapper.Hunyuan3DJobMapper;
import top.riske.gen3d.entity.Hunyuan3DFile;
import top.riske.gen3d.entity.Hunyuan3DJob;
import top.riske.gen3d.http.exception.BisException;
import top.riske.gen3d.service.DataReceivedCallback;
import top.riske.gen3d.service.DeepSeekService;
import top.riske.gen3d.service.Hunyuan3DJobService;
import top.riske.gen3d.util.RequestUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Service
public class Hunyuan3DJobServiceImpl extends ServiceImpl<Hunyuan3DJobMapper, Hunyuan3DJob> implements Hunyuan3DJobService {

    @Resource
    private Hunyuan3DJobMapper hunyuan3DJobMapper;

    @Resource
    private Hunyuan3DFileMapper hunyuan3DFileMapper;

    @Resource
    private DeepSeekService deepSeekService;

    @Value("${gen3d.domain.url}")
    private String serverBaseUrl;

    @Value("${gen3d.file.root.path}")
    private String fileRootUrl;



    @Override
    public List<Hunyuan3DJob> getJobsByAccountId(Long accountId, HttpServletRequest request) {
        // 获取所有任务,以及任务对应的文件
        List<Hunyuan3DJob> jobs = hunyuan3DJobMapper.selectJobWithFileByAccountId(accountId);
        // 构造URL
        for (Hunyuan3DJob job : jobs){
            for (Hunyuan3DFile file : job.getResultFile3Ds()){
                handlePathToUrl(file, request);
            }
        }
        return jobs;
    }


    /**
     * 处理文件路径为URL,如：/2025/9/25/428a79eb36384ca18789abf993590b79/material.mtl
     * 转换为：http://localhost:8080/file/2025/9/25/428a79eb36384ca18789abf993590b79/material.mtl
     * @param file 文件对象，会同步处理此对象
     * @param request 请求对象
     * @return 处理后的文件对象
     */
    @Override
    public Hunyuan3DFile handlePathToUrl(Hunyuan3DFile file, HttpServletRequest request) {
        // 先有先从配置文件中获取
        String baseUrl = serverBaseUrl;
        // 如果都为空，则报错
        if(!StringUtils.hasText(baseUrl) && request == null){
            throw new BisException("系统配置主URL和HttpServletRequest对象都不存在，无法生成文件URL");
        }
        // 若配置文件中，没有配置主URL，则从请求中获取
        if(!StringUtils.hasText(baseUrl)){
            // 若为空，则从请求中获取
            baseUrl = RequestUtils.getBaseUrl(request);
        }
        // 构造URL
        if(StringUtils.hasText(file.getLocalFilePath())){
            file.setLocalFilePath(baseUrl+fileRootUrl+file.getLocalFilePath());
        }
        if(StringUtils.hasText(file.getLocalZipFilePath())){
            file.setLocalZipFilePath(baseUrl+fileRootUrl+file.getLocalZipFilePath());
        }
        if(StringUtils.hasText(file.getLocalMaterialImagePath())){
            file.setLocalMaterialImagePath(baseUrl+fileRootUrl+file.getLocalMaterialImagePath());
        }
        if(StringUtils.hasText(file.getLocalMaterialPath())){
            file.setLocalMaterialPath(baseUrl+fileRootUrl+file.getLocalMaterialPath());
        }
        if(StringUtils.hasText(file.getLocalPreviewImagePath())){
            file.setLocalPreviewImagePath(baseUrl+fileRootUrl+file.getLocalPreviewImagePath());
        }
        return file;
    }

    @Override
    public boolean deleteJob(Long id, Long accountId) {
        Hunyuan3DJob job = this.getById(id);
        if(job == null){
            throw new BisException("任务不存在");
        }
        if(!job.getAccountId().equals(accountId)){
            throw new BisException("任务不属于当前用户");
        }
        // 删除任务，此处实际不删除，将任务所有者设置为0
        // 用于统计模型，减少模型调用次数
        job.setAccountId(0L);
        return this.updateById(job);
    }

    @Override
    public List<Hunyuan3DJob> selectJobWithFileByFullText(String target) {
        return hunyuan3DJobMapper.selectJobByTextFullText(target);
    }

    @Override
    public List<Hunyuan3DJob> searchLikeByAi(String target, HttpServletRequest request) {
        List<Hunyuan3DJob> allJobList = this.list();
        String message = "allJobList:"+ JSONUtil.toJsonStr(allJobList)
                + "target:"+target;
        // 调用AI
        AtomicReference<String> aiResultJsonRef = new AtomicReference<>();
        deepSeekService.chatWithDeepseek(message, new DataReceivedCallback() {
            @Override
            public void onDataReceived(String newData) throws IOException {
                System.out.println(newData);
            }

            @Override
            public void onProcessCompleted(String fullContent) throws IOException {
                aiResultJsonRef.set(fullContent);
            }

            @Override
            public void onError(Exception error) throws IOException {
                error.printStackTrace();
            }
        });
        // 解析json结果
        String aiResultJson = aiResultJsonRef.get();
        JSONObject jsonObject = JSONUtil.parseObj(aiResultJson);
        List<Long> recommendGoodsIds = jsonObject.getJSONArray("recommend").toList(Long.class);
        if(recommendGoodsIds == null || recommendGoodsIds.isEmpty()){
            return new ArrayList<>();
        }
        // 获取推荐商品
        List<Hunyuan3DJob> jobs = this.listByIds(recommendGoodsIds);
        // 获取文件信息
        for(Hunyuan3DJob job : jobs){
            LambdaQueryWrapper<Hunyuan3DFile> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Hunyuan3DFile::getJobId, job.getJobId());
            job.setResultFile3Ds(hunyuan3DFileMapper.selectList(queryWrapper));
            for (Hunyuan3DFile file : job.getResultFile3Ds()){
                this.handlePathToUrl(file, request);
            }
        }

        return jobs;
    }

    @Override
    public Hunyuan3DJob addJobToMine(Long id, Long accountId) {
        Hunyuan3DJob job = this.getById(id);
        if(job == null){
            throw new BisException("任务不存在");
        }
        if(job.getAccountId().equals(accountId)){
            throw new BisException("当前模型已经属于您了");
        }
        job.setAccountId(accountId);
        job.setId(null);
        this.save(job);
        return job;
    }


}
